package com.gt.quality.config;

import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.StpUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.AsyncTaskExecutor;
import org.springframework.core.task.VirtualThreadTaskExecutor;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.AsyncSupportConfigurer;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 开启跨域支持
 *
 * @author: makeJava
 * @createTime: 2026-02-26 21:50
 * @since JDK 21 And SpringBoot 3.X
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    /**
     * 核心线程数 = cpu 核心数 + 1
     */
    private final int core = Runtime.getRuntime().availableProcessors() + 1;

    /**
     * @return CorsConfiguration 跨域允许
     * @author: makeJava
     * @createTime: 2026-02-26 21:50
     * @since JDK 21 And SpringBoot 3.X
     */
    private CorsConfiguration buildConfig() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 1允许任何域名使用
        corsConfiguration.addAllowedOrigin("*");
        // 2允许任何头
        corsConfiguration.addAllowedHeader("*");
        // 3允许任何方法（post、get等）
        corsConfiguration.addAllowedMethod("*");
        return corsConfiguration;
    }

    @Override
    public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
        // 使用线程池配置 AsyncTaskExecutor
        configurer.setTaskExecutor(threadPoolTaskExecutor());
        // 可以根据需要设置超时
        configurer.setDefaultTimeout(5000);
    }

    /**
     * @description: 异步线程池 --优先使用JDK21虚拟线程
     */
    public AsyncTaskExecutor threadPoolTaskExecutor() {
        Runtime.Version version = Runtime.version();
        if (version.toString().contains("21.")) {
            return new VirtualThreadTaskExecutor("virtual-async-task-");
        }
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 最小线程数
        executor.setCorePoolSize(core);
        // 最大线程数
        executor.setMaxPoolSize(core * 2);
        // 队列容量
        executor.setQueueCapacity(core * 2);
        // 线程前缀
        executor.setThreadNamePrefix("async-task-");
        executor.setKeepAliveSeconds(300);
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        executor.initialize();
        return executor;
    }

    @Bean
    public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder) {
        // 禁用时间戳格式 支持 Java 8 时间类型
        return builder
                .featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                .modules(new JavaTimeModule())
                .build();
    }

    /**
     * @return CorsFilter 静态资源过滤
     * @author: makeJava
     * @createTime: 2026-02-26 21:50
     * @since JDK 21 And SpringBoot 3.X
     */
    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        // 4
        source.registerCorsConfiguration("/**", buildConfig());
        return new CorsFilter(source);
    }

    /**
     * Description: 静态资源过滤
     *
     * @author: makeJava
     * @createTime: 2026-02-26 21:50
     * @since JDK 21 And SpringBoot 3.X
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        //ClassPath:/Static/** 静态资源释放
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        //释放swagger
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        //释放webjars
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public SaServletFilter getSaTokenFilter() {
        return new SaServletFilter()
                .addExclude("/static/**", "/css/**", "/js/**", "/images/**");
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        List<String> patterns = new ArrayList<>();
        patterns.add("/saToken/user/login");
        patterns.add("/doc.html");
        patterns.add("/favicon.ico");
        patterns.add("/v3/**");
        patterns.add("/webjars/**");
        patterns.add("/qualitisUser/**");
        patterns.add("/login/**");
        patterns.add("/static/**");
        patterns.add("/svg/**");
        patterns.add("/Vue/**");
        patterns.add("/saToken/verify");
        registry.addInterceptor(new SaInterceptor(handle -> StpUtil.checkLogin()))
                .addPathPatterns("/**")
                .excludePathPatterns(patterns);
        WebMvcConfigurer.super.addInterceptors(registry);
    }
}
